Writing XTERNS


XTERNS are called from the ClockPop app (or the CP Skins app) to get text to add to a message string.
Your code will get two CharPtr strings-one is "Token" which contains the text of the call (usually just the name of your function, but if the user has entered parameters, it will include the parameters separated by colons; you can use the "GetNthVar" function in the code sample below to get the parameters as strings).  The other parameter, "ReturnString" is the current message string.  You should append your text to it.   The message space is physically quite small, so you should generally limit the size of the ReturnString (including your new data) to around 80 characters.  (The CharPtr actually has room for 100 characters ).

An XTERN is a Palm database file of type 'XTRN' (creator is not important).  It must contain a 'code' 1000 resource.  The beginning of the code 1000 research should correspond to a C-function call 

void start(CharPtr Token, CharPtr ReturnString)

(For those of you who have written desk accessories, this is almost identical to a desk accessory except that  the start function is defined differently and the type is different)

For CodeWarrior (5, I'm afraid) you should open the settings box (alt-F7) and 
1. in the "68K Target" preferences, 
put into "Sym Name" the text "XTRN"; 
put into "Resource Name" the text "XTRN", 
put into "Entry Point" the text "start", 
put into "Res Type" the text "code" and 
put into  "ResID" the text "1000".

2. In code generation, in the "68K processor" stuff, make sure "PC relative strings" is checked.  This is because YOU HAVE NO GLOBALS, so if it isn't checked, any string literals will be inaccessible.   (The compiler will NOT warn you that you have no globals, but the application will crash when it find the wrong thing at the address it things the information lies at. This tends to make for random crashes, depending on what information actually happens to be at that address.)

3.  In Palmrez Post Linker, make sure the type is "XTRN".  Supply a creator type.


That's it.

The code for the CP-Nth Memo extern is copied verbatim below (note that the types are pre-OS 3.5, you may need to add "PalmCompatibility.h" or some such if you are using the newer type definintions):

#include <Pilot.h>
#include <SysEvtMgr.h>
#include "StarterRsc.h"
#include <DataMgr.h>



void GetNthVar(CharPtr var, CharPtr Token, Int Nth)
{
	Int i;
	Int i1;
	Int tLen;
	Int Count = Nth+1;
	
	tLen = StrLen(Token);
	i1=0;
	for(i=0;i<tLen;i++)
	{
		if(Token[i]==':') Count--;
		if(Token[i]==':' && Count==0) (i1=i++);
		if(Token[i]==':' && Count <0) break;
	}
	if(Count>0)
	{
		StrCopy(var,"");
		return;
	}
	
	StrNCopy(var, Token+i1+1,i-i1-1);
	var[i-i1-1]=0;

}


void start(CharPtr Token, CharPtr ReturnString)
{
	CharPtr t;
	Int n;
	DmOpenRef d;
	VoidHand h;
	CharPtr p;
	Int SLen;
//	Int MemLen;
	Int CopyLen;
	

	SLen = StrLen(ReturnString);
	t=MemPtrNew(40);
	GetNthVar(t,Token,1);
	n=StrAToI(t);
	MemPtrFree(t);
	if(n>0) n--;
	
	d=DmOpenDatabaseByTypeCreator ('DATA','memo', dmModeReadOnly);
	if(n>=DmNumRecords(d)) n=0;
	h=DmQueryRecord (d, n);
	if(h==0)
	{
		StrCopy(ReturnString,"Memo Deleted!");
		DmReleaseRecord(d,n,false);
		DmCloseDatabase(d);
		return;
	}
	p=MemHandleLock(h);
	CopyLen = StrLen(p)+1;
//	if(CopyLen + SLen > 80) CopyLen = 80-SLen;
	StrNCat(ReturnString, p, SLen + CopyLen);
	ReturnString[SLen+CopyLen]=0;
	MemHandleUnlock(h);
	DmReleaseRecord(d,n,false);
	DmCloseDatabase(d);
	

}
